After last week's little explosive accidents, I needed something simple, something that would just work on the first try, and ideally something that a trained monkey could do, given propper instructions. So I decided to follow a tutorial on how to make a web server using Arduino IDE and an ESP32. The process was quite straightforward, and I had the whole thing running in a few minutes. Perhaps the only smaller difficulty was figuring out, which exact ESP I have so that I could choose the proper one in Arduino IDE.
Overall, I ended up with two LEDs connected to the ESP. The ESP then connected to my hotspot and started hosting a dynamic website with two buttons that allowed me to control the LEDs.
It would be pretty boring if I concluded this week with just two LEDs, so I decided I should at least try to improve it a little bit. And so I added two more LEDs and rewrote the code, to work as a simple binary counter. The hardest thing about it was to figuring which pins I could actually use.
Even after finding this image with the pinout for this exact ESP, it took me some time before I realized which of them were actually usable for me. I eventually settled with pins 26, 27, 32 and 33 (that is the GPIO on the picture), which seemed to do the job.
The changes to the code were also pretty straightforward. I added initialization for the pins I used, then I added a simple integer variable called counter. I then displayed the current counter state on the screen and changed the buttons a little so they would turn gray, when the maximum or minimum of the counter was reached.
// Web Page Heading
client.println("<body><h1>ESP32 Web Server</h1>");
// Display current count
client.println("<p>Counter: " + (String)counter + "</p>");
// adder button
if (counter < 15) {
client.println("<p><a href=\"/26/add\"><button class=\"button\">ADD</button></a></p>");
} else {
client.println("<p><button class=\"button button2\">ADD</button></a></p>");
}
// subtracter button
if (counter > 0) {
client.println("<p><a href=\"/27/sub\"><button class=\"button\">SUBTRACT</button></a></p>");
} else {
client.println("<p><button class=\"button button2\">SUBTRACT</button></a></p>");
}
client.println("</body></html>");
Then it was just a case of detecting when a button got pressed and increasing or decreasing the counter variable.
// detect button presses
if (header.indexOf("GET /26/add") >= 0) {
counter += 1;
Serial.println("ADDING");
output26State = "on";
digitalWrite(output26, HIGH);
} else if (header.indexOf("GET /27/sub") >= 0) {
counter -= 1;
Serial.println("SUBTRACTING");
output26State = "off";
digitalWrite(output26, LOW);
}
All that was left to do was decode the counter variable into binary and toggle the appropriate LEDs on or off.
int holder = counter;
if (holder >= 8) {
holder -= 8;
digitalWrite(output27, HIGH);
} else {
digitalWrite(output27, LOW);
}
if (holder >= 4) {
holder -= 4;
digitalWrite(output26, HIGH);
} else {
digitalWrite(output26, LOW);
}
if (holder >= 2) {
holder -= 2;
digitalWrite(output25, HIGH);
} else {
digitalWrite(output25, LOW);
}
if (holder >= 1) {
holder -= 1;
digitalWrite(output33, HIGH);
} else {
digitalWrite(output33, LOW);
}
The result was a nice little binary counter controlled via the website interface.
If you would like to try this as well, the full code is here:
// Load Wi-Fi library
#include <WiFi.h>
// Replace with your network credentials
const char* ssid = "DESKTOP-1FKDNL1 3316";
const char* password = "ahojkamo";
// Set web server port number to 80
WiFiServer server(80);
// Variable to store the HTTP request
String header;
// Auxiliar variables to store the current output state
String output26State = "off";
String output27State = "off";
// Assign output variables to GPIO pins
const int output33 = 32;
const int output25 = 33;
const int output26 = 26;
const int output27 = 27;
// Current time
unsigned long currentTime = millis();
// Previous time
unsigned long previousTime = 0;
// Define timeout time in milliseconds (example: 2000ms = 2s)
const long timeoutTime = 2000;
int counter = 0;
void setup() {
Serial.begin(115200);
// Initialize the output variables as outputs
pinMode(output33, OUTPUT);
pinMode(output25, OUTPUT);
pinMode(output26, OUTPUT);
pinMode(output27, OUTPUT);
// Set outputs to LOW
digitalWrite(output33, LOW);
digitalWrite(output25, LOW);
digitalWrite(output26, LOW);
digitalWrite(output27, LOW);
// Connect to Wi-Fi network with SSID and password
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
// Print local IP address and start web server
Serial.println("");
Serial.println("WiFi connected.");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
server.begin();
}
void loop(){
WiFiClient client = server.available(); // Listen for incoming clients
if (client) { // If a new client connects,
currentTime = millis();
previousTime = currentTime;
Serial.println("New Client."); // print a message out in the serial port
String currentLine = ""; // make a String to hold incoming data from the client
while (client.connected() && currentTime - previousTime <= timeoutTime) { // loop while the client's connected
currentTime = millis();
if (client.available()) { // if there's bytes to read from the client,
char c = client.read(); // read a byte, then
Serial.write(c); // print it out the serial monitor
header += c;
if (c == '\n') { // if the byte is a newline character
// if the current line is blank, you got two newline characters in a row.
// that's the end of the client HTTP request, so send a response:
if (currentLine.length() == 0) {
// HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
// and a content-type so the client knows what's coming, then a blank line:
client.println("HTTP/1.1 200 OK");
client.println("Content-type:text/html");
client.println("Connection: close");
client.println();
// detect button presses
if (header.indexOf("GET /26/add") >= 0) {
counter += 1;
Serial.println("ADDING");
output26State = "on";
digitalWrite(output26, HIGH);
} else if (header.indexOf("GET /27/sub") >= 0) {
counter -= 1;
Serial.println("SUBTRACTING");
output26State = "off";
digitalWrite(output26, LOW);
}
int holder = counter;
if (holder >= 8) {
holder -= 8;
digitalWrite(output27, HIGH);
} else {
digitalWrite(output27, LOW);
}
if (holder >= 4) {
holder -= 4;
digitalWrite(output26, HIGH);
} else {
digitalWrite(output26, LOW);
}
if (holder >= 2) {
holder -= 2;
digitalWrite(output25, HIGH);
} else {
digitalWrite(output25, LOW);
}
if (holder >= 1) {
holder -= 1;
digitalWrite(output33, HIGH);
} else {
digitalWrite(output33, LOW);
}
// Display the HTML web page
client.println("<!DOCTYPE html><html>");
client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
client.println("<link rel=\"icon\" href=\"data:,\">");
// CSS to style the on/off buttons
// Feel free to change the background-color and font-size attributes to fit your preferences
client.println("<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}");
client.println(".button { background-color: #4CAF50; border: none; color: white; padding: 16px 40px;");
client.println("text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}");
client.println(".button2 {background-color: #555555;}</style></head>");
// Web Page Heading
client.println("<body><h1>ESP32 Web Server</h1>");
// Display current count
client.println("<p>Counter: " + (String)counter + "</p>");
// adder button
if (counter < 15) {
client.println("<p><a href=\"/26/add\"><button class=\"button\">ADD</button></a></p>");
} else {
client.println("<p><button class=\"button button2\">ADD</button></a></p>");
}
// subtracter button
if (counter > 0) {
client.println("<p><a href=\"/27/sub\"><button class=\"button\">SUBTRACT</button></a></p>");
} else {
client.println("<p><button class=\"button button2\">SUBTRACT</button></a></p>");
}
client.println("</body></html>");
// The HTTP response ends with another blank line
client.println();
// Break out of the while loop
break;
} else { // if you got a newline, then clear currentLine
currentLine = "";
}
} else if (c != '\r') { // if you got anything else but a carriage return character,
currentLine += c; // add it to the end of the currentLine
}
}
}
// Clear the header variable
header = "";
// Close the connection
client.stop();
Serial.println("Client disconnected.");
Serial.println("");
}
}